//Copyright (c) Microsoft Corporation.  All rights reserved.

#pragma once

#include "DWriteEnums.h"

    namespace DWrite = Microsoft::WindowsAPICodePack::DirectX::DirectWrite;

namespace  Microsoft { namespace WindowsAPICodePack { namespace DirectX { namespace DirectWrite { 


/// <summary>
/// Line spacing parameters.
/// </summary>
/// <remarks>
/// For the default line spacing method, spacing depends solely on the content.
/// For uniform line spacing, the given line height will override the content.
/// </remarks>    
public value struct LineSpacing
{
public:

    /// <summary>
    /// Constructor for LineSpacing
    /// </summary>
    /// <param name="lineSpacingMethod">Initializes the LineSpaceingMethod field.</param>
    /// <param name="height">Initializes the Height field.</param>
    /// <param name="baseline">Initializes the Baseline field.</param>
    LineSpacing(
        DWrite::LineSpacingMethod lineSpacingMethod,
        Single height,
        Single baseline
        ) : LineSpacingMethod(lineSpacingMethod), Height(height), Baseline(baseline)
    { }



    /// <summary>
    /// How line height is determined.
    /// </summary>
    DWrite::LineSpacingMethod LineSpacingMethod;

    /// <summary>
    /// The line height, or rather distance between one baseline to another.
    /// </summary>
    Single Height;

    /// <summary>
    /// Distance from top of line to baseline. A reasonable ratio to Height is 80%.
    /// </summary>
    Single Baseline;

};
/// <summary>
/// Specifies a range of text positions where format is applied.
/// </summary>
public value struct TextRange
{
public:
    /// <summary>
    /// Constructor for TextRange
    /// </summary>
    TextRange (
        UINT32 startPosition,
        UINT32 length
        ) : StartPosition(startPosition), Length(length)
        { }

    /// <summary>
    /// The start text position of the range.
    /// </summary>
    UINT32 StartPosition;

    /// <summary>
    /// The number of text positions in the range.
    /// </summary>
    UINT32 Length;
internal:
    void CopyFrom(
        const DWRITE_TEXT_RANGE & nativeStruct
         )
    {
        StartPosition = nativeStruct.startPosition;
        Length = nativeStruct.length;
    }

    void CopyTo(
        DWRITE_TEXT_RANGE *pNativeStruct
        )
    {
        pNativeStruct->startPosition = StartPosition;
        pNativeStruct->length = Length;
    }    
};

/// <summary>
/// Geometry enclosing of text positions.
/// </summary>
public value struct HitTestMetrics
{
public:
    /// <summary>
    /// Constructor for HitTestMetrics
    /// </summary>
    HitTestMetrics(
        UINT32 textPosition,
        UINT32 length,
        FLOAT left,
        FLOAT top,
        FLOAT width,
        FLOAT height,
        UINT32 bidiLevel,
        Boolean isText,
        Boolean isTrimmed
   ) : 
        TextPosition(textPosition),
        Length(length),
        Left(left),
        Top(top),
        Width(width),
        Height(height),
        BidiLevel(bidiLevel),
        IsText(isText),
        IsTrimmed(isTrimmed)
    { }

    /// <summary>
    /// First text position within the geometry.
    /// </summary>
    UINT32 TextPosition;

    /// <summary>
    /// Number of text positions within the geometry.
    /// </summary>
    UINT32 Length;

    /// <summary>
    /// Left position of the top-left coordinate of the geometry.
    /// </summary>
    FLOAT Left;

    /// <summary>
    /// Top position of the top-left coordinate of the geometry.
    /// </summary>
    FLOAT Top;

    /// <summary>
    /// Geometry's width.
    /// </summary>
    FLOAT Width;

    /// <summary>
    /// Geometry's height.
    /// </summary>
    FLOAT Height;

    /// <summary>
    /// Bidi level of text positions enclosed within the geometry.
    /// </summary>
    UINT32 BidiLevel;

    /// <summary>
    /// Geometry encloses text?
    /// </summary>
    Boolean IsText;

    /// <summary>
    /// Range is trimmed.
    /// </summary>
    Boolean IsTrimmed;

internal:
    void CopyFrom(
         const DWRITE_HIT_TEST_METRICS & nativeStruct
         )
    {
        TextPosition = nativeStruct.textPosition;
        Length = nativeStruct.length;
        Left = nativeStruct.left;
        Top = nativeStruct.top;
        Width = nativeStruct.width;
        Height = nativeStruct.height;
        BidiLevel = nativeStruct.bidiLevel;
        IsText = nativeStruct.isText != 0;
        IsTrimmed = nativeStruct.isTrimmed != 0;
    }

    void CopyTo(
        DWRITE_HIT_TEST_METRICS *pNativeStruct
        )
    {
        pNativeStruct->textPosition = TextPosition;
        pNativeStruct->length = Length;
        pNativeStruct->left = Left;
        pNativeStruct->top = Top;
        pNativeStruct->width = Width;
        pNativeStruct->height = Height;
        pNativeStruct->bidiLevel = BidiLevel;
        pNativeStruct->isText = IsText;
        pNativeStruct->isTrimmed = IsTrimmed;
    }
};


/// <summary>
/// Contains information about a formatted line of text.
/// </summary>
public value struct LineMetrics
{
public:
        /// <summary>
        /// Constructor for LineMetrics
        /// </summary>
        LineMetrics(
            UINT32 length,
            UINT32 trailingWhitespaceLength,
            UINT32 newlineLength,
            FLOAT height,
            FLOAT baseline,
            Boolean isTrimmed
       ) : 
            Length(length),
            TrailingWhitespaceLength(trailingWhitespaceLength),
            NewlineLength(newlineLength),
            Height(height),
            Baseline(baseline),
            IsTrimmed(isTrimmed)
        { }
    /// <summary>
    /// The number of total text positions in the line.
    /// This includes any trailing whitespace and newline characters.
    /// </summary>
    UINT32 Length;

    /// <summary>
    /// The number of whitespace positions at the end of the line.  Newline
    /// sequences are considered whitespace.
    /// </summary>
    UINT32 TrailingWhitespaceLength;

    /// <summary>
    /// The number of characters in the newline sequence at the end of the line.
    /// If the count is zero, then the line was either wrapped or it is the
    /// end of the text.
    /// </summary>
    UINT32 NewlineLength;

    /// <summary>
    /// Height of the line as measured from top to bottom.
    /// </summary>
    FLOAT Height;

    /// <summary>
    /// Distance from the top of the line to its baseline.
    /// </summary>
    FLOAT Baseline;

    /// <summary>
    /// The line is trimmed.
    /// </summary>
    Boolean IsTrimmed;

    internal:
        void CopyFrom(
             const DWRITE_LINE_METRICS & nativeStruct
             )
        {
            Length = nativeStruct.length;
            TrailingWhitespaceLength = nativeStruct.trailingWhitespaceLength;
            NewlineLength = nativeStruct.newlineLength;
            Height = nativeStruct.height;
            Baseline = nativeStruct.baseline;
            IsTrimmed = nativeStruct.isTrimmed != 0;
        }

        void CopyTo(
            DWRITE_LINE_METRICS *pNativeStruct
            )
        {
            pNativeStruct->length = Length;

            pNativeStruct->trailingWhitespaceLength = TrailingWhitespaceLength;
            pNativeStruct->newlineLength = NewlineLength;
            pNativeStruct->height = Height;
            pNativeStruct->baseline = Baseline;
            pNativeStruct->isTrimmed = IsTrimmed;
        }
};

/// <summary>
/// Overall metrics associated with text after layout.
/// All coordinates are in device independent pixels (DIPs).
/// </summary>
public value struct TextMetrics
{
public:
        /// <summary>
        /// Constructor for TextMetrics
        /// </summary>
        TextMetrics(
            FLOAT left,
            FLOAT top,
            FLOAT width,
            FLOAT widthIncludingTrailingWhitespace,
            FLOAT height,
            FLOAT layoutWidth,
            FLOAT layoutHeight,
            UINT32 maxBidiReorderingDepth,
            UINT32 lineCount)
                : 
            Left(left),
            Top(top),
            Width(width),
            WidthIncludingTrailingWhitespace(widthIncludingTrailingWhitespace),
            Height(height),
            LayoutWidth(layoutWidth),
            LayoutHeight(layoutHeight),
            MaxBidiReorderingDepth(maxBidiReorderingDepth),
            LineCount(lineCount)
        { }

    /// <summary>
    /// Left-most point of formatted text relative to layout box
    /// (excluding any glyph overhang).
    /// </summary>
    FLOAT Left;

    /// <summary>
    /// Top-most point of formatted text relative to layout box
    /// (excluding any glyph overhang).
    /// </summary>
    FLOAT Top;

    /// <summary>
    /// The width of the formatted text ignoring trailing whitespace
    /// at the end of each line.
    /// </summary>
    FLOAT Width;

    /// <summary>
    /// The width of the formatted text taking into account the
    /// trailing whitespace at the end of each line.
    /// </summary>
    FLOAT WidthIncludingTrailingWhitespace;

    /// <summary>
    /// The height of the formatted text. The height of an empty string
    /// is determined by the size of the default font's line height.
    /// </summary>
    FLOAT Height;

    /// <summary>
    /// Initial width given to the layout. Depending on whether the text
    /// was wrapped or not, it can be either larger or smaller than the
    /// text content width.
    /// </summary>
    FLOAT LayoutWidth;

    /// <summary>
    /// Initial height given to the layout. Depending on the length of the
    /// text, it may be larger or smaller than the text content height.
    /// </summary>
    FLOAT LayoutHeight;

    /// <summary>
    /// The maximum reordering count of any line of text, used
    /// to calculate the most number of hit-testing boxes needed.
    /// If the layout has no bidirectional text or no text at all,
    /// the minimum level is 1.
    /// </summary>
    UINT32 MaxBidiReorderingDepth;

    /// <summary>
    /// Total number of lines.
    /// </summary>
    UINT32 LineCount;


    internal:
        void CopyFrom(
             const DWRITE_TEXT_METRICS & nativeStruct
             )
        {
            Left = nativeStruct.left;
            Top = nativeStruct.top;
            Width = nativeStruct.width;
            WidthIncludingTrailingWhitespace = nativeStruct.widthIncludingTrailingWhitespace;
            Height = nativeStruct.height;
            LayoutWidth = nativeStruct.layoutWidth;
            LayoutHeight = nativeStruct.layoutHeight;
            MaxBidiReorderingDepth = nativeStruct.maxBidiReorderingDepth;
            LineCount = nativeStruct.lineCount;
        }

        void CopyTo(
            DWRITE_TEXT_METRICS *pNativeStruct
            )
        {
            pNativeStruct->left = Left ;
            pNativeStruct->top = Top;
            pNativeStruct->width = Width;
            pNativeStruct->widthIncludingTrailingWhitespace = WidthIncludingTrailingWhitespace;
            pNativeStruct->height = Height;
            pNativeStruct->layoutWidth = LayoutWidth;
            pNativeStruct->layoutHeight = LayoutHeight;
            pNativeStruct->maxBidiReorderingDepth = MaxBidiReorderingDepth;
            pNativeStruct->lineCount = LineCount;
        }
};

/// <summary>
/// Holds information about how much any visible pixels
/// (in DIPs) overshoot each side of the layout or inline objects.
/// </summary>
/// <remarks>
/// Positive overhangs indicate that the visible area extends outside the layout
/// box or inline object, while negative values mean there is whitespace inside.
/// The returned values are unaffected by rendering transforms or pixel snapping.
/// Additionally, they may not exactly match final target's pixel bounds after
/// applying grid fitting and hinting.
/// </remarks>
public value struct OverhangMetrics
{
public:
    /// <summary>
    /// Constructor for OverhangMetrics
    /// </summary>
    OverhangMetrics (
        FLOAT left,
        FLOAT top,
        FLOAT right,
        FLOAT bottom ) 
        :
        Left(left),
        Top(top),
        Right(right),
        Bottom(bottom)
    { }

    /// <summary>
    /// The distance from the left-most visible DIP to its left alignment edge.
    /// </summary>
    FLOAT Left;

    /// <summary>
    /// The distance from the top-most visible DIP to its top alignment edge.
    /// </summary>
    FLOAT Top;

    /// <summary>
    /// The distance from the right-most visible DIP to its right alignment edge.
    /// </summary>
    FLOAT Right;

    /// <summary>
    /// The distance from the bottom-most visible DIP to its bottom alignment edge.
    /// </summary>
    FLOAT Bottom;

    internal:
        void CopyFrom(
            const DWRITE_OVERHANG_METRICS & nativeStruct
             )
        {
            Left = nativeStruct.left;
            Top = nativeStruct.top;
            Right = nativeStruct.right;
            Bottom = nativeStruct.bottom;
        }

        void CopyTo(
            DWRITE_OVERHANG_METRICS *pNativeStruct
            )
        {
            pNativeStruct->left = Left ;
            pNativeStruct->top = Top;
            pNativeStruct->right = Right;
            pNativeStruct->bottom = Bottom;
        }
};


/// <summary>
/// Contains information about a glyph cluster.
/// </summary>
public value struct ClusterMetrics
{
public:
    /// <summary>
    /// Constructor for ClusterMetrics
    /// </summary>
    ClusterMetrics (
        FLOAT width,
        UINT16 length,
        UINT16 canWrapLineAfter,
        UINT16 isWhitespace,
        UINT16 isNewline,
        UINT16 isSoftHyphen,
        UINT16 isRightToLeft) 
        :
        Width(width),
        Length(length),
        CanWrapLineAfter(canWrapLineAfter),
        IsWhitespace(isWhitespace),
        IsNewline(isNewline),
        IsSoftHyphen(isSoftHyphen),
        IsRightToLeft(isRightToLeft)
    { }

    /// <summary>
    /// The total advance width of all glyphs in the cluster.
    /// </summary>
    FLOAT Width;

    /// <summary>
    /// The number of text positions in the cluster.
    /// </summary>
    UINT16 Length;

    /// <summary>
    /// Indicate whether line can be broken right after the cluster.
    /// </summary>
    UINT16 CanWrapLineAfter;

    /// <summary>
    /// Indicate whether the cluster corresponds to whitespace character.
    /// </summary>
    UINT16 IsWhitespace;

    /// <summary>
    /// Indicate whether the cluster corresponds to a newline character.
    /// </summary>
    UINT16 IsNewline;

    /// <summary>
    /// Indicate whether the cluster corresponds to soft hyphen character.
    /// </summary>
    UINT16 IsSoftHyphen;

    /// <summary>
    /// Indicate whether the cluster is read from right to left.
    /// </summary>
    UINT16 IsRightToLeft;

    internal:
        void CopyFrom(
            const DWRITE_CLUSTER_METRICS & nativeStruct
             )
        {
            Width = nativeStruct.width;
            Length = nativeStruct.length;
            CanWrapLineAfter = nativeStruct.canWrapLineAfter;
            IsWhitespace = nativeStruct.isWhitespace;
            IsNewline = nativeStruct.isNewline;
            IsSoftHyphen = nativeStruct.isSoftHyphen;
            IsRightToLeft = nativeStruct.isRightToLeft;
        }

        void CopyTo(
            DWRITE_CLUSTER_METRICS *pNativeStruct
            )
        {
            pNativeStruct->width = Width;
            pNativeStruct->length = Length;
            pNativeStruct->canWrapLineAfter = CanWrapLineAfter;
            pNativeStruct->isWhitespace = IsWhitespace;
            pNativeStruct->isNewline = IsNewline;
            pNativeStruct->isSoftHyphen = IsSoftHyphen;
            pNativeStruct->isRightToLeft = IsRightToLeft;
        }

};

/// <summary>
/// Specifies the trimming option for text overflowing the layout box.
/// </summary>
public value struct Trimming
{
public:
    /// <summary>
    /// Constructor for Trimming
    /// </summary>
    Trimming (
        TrimmingGranularity granularity,
        UINT32 delimiter,
        UINT32 delimiterCount) 
        :
        Granularity(granularity),
        Delimiter(delimiter),
        DelimiterCount(delimiterCount)
    { }

    /// <summary>
    /// Text granularity of which trimming applies.
    /// </summary>
    TrimmingGranularity Granularity;

    /// <summary>
    /// Character code used as the delimiter signaling the beginning of the portion of text to be preserved,
    /// most useful for path ellipsis, where the delimeter would be a slash.
    /// </summary>
    UINT32 Delimiter;

    /// <summary>
    /// How many occurences of the delimiter to step back.
    /// </summary>
    UINT32 DelimiterCount;

internal:
    void CopyFrom(
        const DWRITE_TRIMMING & nativeStruct
         )
    {
        Granularity = static_cast<TrimmingGranularity>(nativeStruct.granularity);
        Delimiter = nativeStruct.delimiter;
        DelimiterCount = nativeStruct.delimiterCount;
    }

    void CopyTo(
        DWRITE_TRIMMING *pNativeStruct
        )
    {
        pNativeStruct->granularity = static_cast<DWRITE_TRIMMING_GRANULARITY>(Granularity);
        pNativeStruct->delimiter = Delimiter;
        pNativeStruct->delimiterCount = DelimiterCount;
    }
};

/// <summary>
/// The Matrix structure specifies the graphics transform to be applied
/// to rendered glyphs.
/// </summary>
public value struct Matrix
{
    /// <summary>
    /// Constructor for Trimming
    /// </summary>
    Matrix (
        FLOAT m11,
        FLOAT m12,
        FLOAT m21,
        FLOAT m22,
        FLOAT dx,
        FLOAT dy)
        :
        M11(m11),
        M12(m12),
        M21(m21),
        M22(m22),
        Dx(dx),
        Dy(dy)
    { }

    /// <summary>
    /// Horizontal scaling / cosine of rotation
    /// </summary>
    FLOAT M11;

    /// <summary>
    /// Vertical shear / sine of rotation
    /// </summary>
    FLOAT M12;

    /// <summary>
    /// Horizontal shear / negative sine of rotation
    /// </summary>
    FLOAT M21;

    /// <summary>
    /// Vertical scaling / cosine of rotation
    /// </summary>
    FLOAT M22;

    /// <summary>
    /// Horizontal shift (always orthogonal regardless of rotation)
    /// </summary>
    FLOAT Dx;

    /// <summary>
    /// Vertical shift (always orthogonal regardless of rotation)
    /// </summary>
    FLOAT Dy;

internal:
    void CopyFrom(
        const DWRITE_MATRIX & nativeStruct
         )
    {
        M11 = nativeStruct.m11;
        M12 = nativeStruct.m12;
        M21 = nativeStruct.m21;
        M22 = nativeStruct.m22;
        Dx = nativeStruct.dx;
        Dy = nativeStruct.dy;
    }

    void CopyTo(
        DWRITE_MATRIX *pNativeStruct
        )
    {
        pNativeStruct->m11 = M11;
        pNativeStruct->m12 = M12;
        pNativeStruct->m21 = M21;
        pNativeStruct->m22 = M22;
        pNativeStruct->dx = Dx;
        pNativeStruct->dy = Dy;
    }};

} } } }